﻿// Decompiled with JetBrains decompiler
// Type: Microsoft.InfoCards.Psha1DerivedKeyGenerator
// Assembly: infocard, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
// MVID: 8E14765A-6610-409A-BA36-099A0642905D
// Assembly location: E:\git\ALLIDA\windll\infocard.exe

using Microsoft.InfoCards.Diagnostics;
using System;
using System.Security.Cryptography;

namespace Microsoft.InfoCards
{
  internal sealed class Psha1DerivedKeyGenerator
  {
    private byte[] key;

    public Psha1DerivedKeyGenerator(byte[] key)
    {
      if (key == null)
        throw InfoCardTrace.ThrowHelperArgumentNull(nameof (key));
      this.key = key;
    }

    public byte[] GenerateDerivedKey(byte[] label, byte[] nonce, int derivedKeySize, int position)
    {
      if (label == null)
        throw InfoCardTrace.ThrowHelperArgumentNull(nameof (label));
      if (nonce == null)
        throw InfoCardTrace.ThrowHelperArgumentNull(nameof (nonce));
      return new Psha1DerivedKeyGenerator.ManagedPsha1(this.key, label, nonce).GetDerivedKey(derivedKeySize, position);
    }

    private sealed class ManagedPsha1
    {
      private byte[] aValue;
      private byte[] buffer;
      private byte[] chunk;
      private KeyedHashAlgorithm hmac;
      private int index;
      private int position;
      private byte[] secret;
      private byte[] seed;

      public ManagedPsha1(byte[] secret, byte[] label, byte[] seed)
      {
        this.secret = secret;
        this.seed = new byte[checked (label.Length + seed.Length)];
        label.CopyTo((Array) this.seed, 0);
        seed.CopyTo((Array) this.seed, label.Length);
        this.aValue = this.seed;
        this.chunk = new byte[0];
        this.index = 0;
        this.position = 0;
        this.hmac = (KeyedHashAlgorithm) new HMACSHA1(secret, true);
        this.buffer = new byte[checked (unchecked (this.hmac.HashSize / 8) + this.seed.Length)];
      }

      public byte[] GetDerivedKey(int derivedKeySize, int position)
      {
        if (derivedKeySize < 0)
          throw InfoCardTrace.ThrowHelperError((Exception) new ArgumentOutOfRangeException(nameof (derivedKeySize), SR.GetString("ValueMustBeNonNegative")));
        if (this.position > position)
          throw InfoCardTrace.ThrowHelperError((Exception) new ArgumentOutOfRangeException(nameof (position), SR.GetString("ValueMustBeInRange", (object) 0, (object) this.position)));
        while (this.position < position)
        {
          int num = (int) this.GetByte();
        }
        int length = derivedKeySize / 8;
        byte[] numArray = new byte[length];
        for (int index = 0; index < length; ++index)
          numArray[index] = this.GetByte();
        return numArray;
      }

      private byte GetByte()
      {
        if (this.index >= this.chunk.Length)
        {
          this.hmac.Initialize();
          this.aValue = this.hmac.ComputeHash(this.aValue);
          this.aValue.CopyTo((Array) this.buffer, 0);
          this.seed.CopyTo((Array) this.buffer, this.aValue.Length);
          this.hmac.Initialize();
          this.chunk = this.hmac.ComputeHash(this.buffer);
          this.index = 0;
        }
        ++this.position;
        return this.chunk[this.index++];
      }
    }
  }
}
